package com.yyhu.auto

import com.android.build.gradle.AppExtension
import com.android.build.gradle.api.ApplicationVariant
import com.android.build.gradle.api.BaseVariantOutput
import org.apache.http.util.TextUtils
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.provider.ProviderFactory
import org.json.JSONArray
import org.json.JSONObject

import javax.inject.Inject
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardCopyOption

class AutoBuild implements Plugin<Project> {

    String ddPic = "https://p3.itc.cn/q_70/images03/20211015/d4071c52357a437193486b62e51d2281.png"

    String apkFtpPath = ""
    String appVersion = ""
    String appName = ""
    String gitCommitMsg = ""
    String assembleParams = "";

    private final ProviderFactory providers

    @Inject
    AutoBuild(ProviderFactory providers) {
        this.providers = providers
    }

    String depAppName = ""
    String depAppVersion = ""
    String deviceList = ""
    String tmpPassword = ""
    String tmpAccount = ""
    int selfTestPlanId = 0

    String submitTmpResult = ""
    String ddAtUser = ""
    String ddAtUserMobile = ""

    String ddAtFailUser = ""

    String tmpUser = ""

    @Override
    void apply(Project project) {
        // 向extension container保存para参数
        project.extensions.create("para", AutoPluginExtension)
        project.afterEvaluate {
            String customParam = project.properties["buildParam"] ?: ""
            depAppName = project.properties["depAppName"] ?: ""
            depAppVersion = project.properties["depAppVersion"] ?: ""
            tmpPassword = project.properties["tmpPassword"] ?: ""
            tmpAccount = project.properties["tmpAccount"] ?: ""
            deviceList = project.properties["deviceList"] ?: ""
            ddAtFailUser = project.properties["ddAtFailUser"] ?: ""
            ddAtUser = project.properties["ddAtUser"] ?: ""
            ddAtUserMobile = project.properties["ddAtMobile"] ?: ""
            tmpUser = project.properties["tmpAtUser"] ?: ""

            String selfStr = project.properties["selfTestPlanId"] ?: ""
            if (!TextUtils.isBlank(selfStr)) {
                selfTestPlanId = selfStr.toInteger()
            }
            String assembleContent = project.para.buildParam ?: ""
            if (customParam.size() > 0) {
                assembleParams = customParam
            } else if (assembleContent.size() > 0) {
                assembleParams = assembleContent
            }
            appVersion = project.para.appVersion

            def jenkinsName = getJenkinsApkName()
            if (TextUtils.isBlank(jenkinsName)) {
                appName = project.para.appName
            } else {
                appName = jenkinsName
            }
            println "********************************************************************************"
            println "depAppName:${depAppName}"
            println "depAppVersion:${depAppVersion}"
            println "deviceList:${deviceList}"
            println "selfTestPlanId:${selfTestPlanId}"
            println "jenkinsName:${jenkinsName}"
            println "appName    :${project.para.appName}"
            println "cmdParam   :${customParam}"
            println "buildParam :${assembleContent}"
            println "***webHook :${project.para.webHook}"
            println "***sendMsg :${project.para.sendMsg}"
            println "appVersion :${appVersion}"
            println "tmpAccount :${tmpAccount}"
            println "projectId :${project.para.projectId}"
            println "********************************************************************************"
            // 向project对象添加任务
            project.task('autoBuild', type: MyTask) {
                doFirst {

                }
                if (assembleParams.size() > 0) {
                    String assembleParamStr = ""
                    for (String param : assembleParams.split("#")) {
                        String capitalizedStr = param.replaceFirst(param.substring(0, 1), param.substring(0, 1).toUpperCase());
                        assembleParamStr += capitalizedStr
                    }
                    println "开始打包,打包命令：assemble${assembleParamStr}"
                    dependsOn("assemble${assembleParamStr}")
                } else {
                    println "无效参数 buildParam"
                }
                doLast {
                    def localApkPath = findFinalApkPath(project, assembleParams, appVersion)
                    def ftpPath = getFtpFilePath(localApkPath)
                    println("✅ APK FTP 地址," + ftpPath)
                    apkFtpPath = ftpPath
                    gitCommitMsg = getGitCommandResult(project, "git log -1 --pretty=%B")
                    String tmpUploadStr = uploadTmp(project)
                    def sendMsg = project.para.sendMsg + "\n\n**项目名称:**\n\n${appName}" + tmpUploadStr + "\n\n" + getGitInfo(project)
                    if (!TextUtils.isBlank(project.para.webHook)) {
                        sendMsgToDing(project.para.webHook, sendMsg, ftpPath)
                    }
                }
            }
        }
    }

    String uploadTmp(Project project) {
        String tmpUploadStr = ""
        println("deviceList:$deviceList")
        if (TextUtils.isBlank(tmpAccount) || TextUtils.isBlank(tmpPassword)) {
            tmpUploadStr = ""
            return tmpUploadStr
        }
        RsaHelper rsaHelper = new RsaHelper();
        String psw = rsaHelper.rsaDecrypt(tmpPassword)
        if (TextUtils.isBlank(psw)) {
            tmpUploadStr = "\n\n**TMP提测信息:**\n\n- 自动提交失败\n\n- 密码解析错误"
            return tmpUploadStr
        }
        if (!TextUtils.isBlank(deviceList)) {
            submitTmpResult = "0"
            try {
                def tmpBean = new TmpInfoBean()
                tmpBean.apkFtpPath = apkFtpPath
                tmpBean.apkVersion = appVersion
                tmpBean.gitCommitMsg = gitCommitMsg
                tmpBean.appName = appName
                tmpBean.tmpAccount = tmpAccount
                tmpBean.tmpPassword = psw
                tmpBean.projectId = project.para.projectId
                tmpBean.depAppName = depAppName
                TmpUserIdHelp userBean = new TmpUserIdHelp()
                tmpBean.relatedMemberId = userBean.getTmpUser(tmpUser.split("#").toList())
                tmpBean.depAppVersion = depAppVersion
                //Cit自测用例
                tmpBean.selfTestPlanId = selfTestPlanId
                String deviceStr = deviceList
                ArrayList<String> deviceList = new ArrayList()
                for (String itemStr : deviceStr.split("#")) {
                    deviceList.add(itemStr)
                }
                tmpBean.deviceList = deviceList
                def uploadTmp = new UploadTmp(tmpBean)
                def netResultStr = uploadTmp.loginTmp()
                tmpUploadStr = netResultStr
                try {
                    JSONObject uploadObj = new JSONObject(netResultStr)
                    int code = uploadObj.get("code")
                    if (code == 1) {
                        submitTmpResult = "1"
                        String tmpAccountTips = ""
                        try {
                            tmpSubmitUrl = uploadObj.getJSONObject("data").optString("submitTestUrl", "")
                            tmpAccountTips = "\n\n- TMP地址:$tmpSubmitUrl"
                        } catch (Exception e) {
                            e.printStackTrace()
                        }
                        tmpUploadStr = "\n\n**TMP提测信息:**\n\n- 自动提交成功\n\n${getTmpTips(tmpBean)}${tmpAccountTips}"
                    } else {
                        tmpUploadStr = "\n\n**TMP提测信息:**\n\n- 自动提交失败\n\n- ${netResultStr}"
                    }
                } catch (Exception e) {
                    e.printStackTrace()
                }
            } catch (Exception e) {
                e.printStackTrace()
                tmpUploadStr = "\n\n**TMP提测信息:**\n\n- 自动提交失败\n\n- gitLabEvent:${gitLabEvent}"
            }
        }
        return tmpUploadStr
    }

    String tmpSubmitUrl = ""

    String getTmpTips(TmpInfoBean tmpInfoBean) {
        StringBuilder builder = new StringBuilder()
        def deviceStr = "- 提测机型:"
        for (String deviceName : tmpInfoBean.deviceList) {
            deviceStr = deviceStr + "\n\n- " + deviceName
        }
        builder.append(deviceStr)
        if (!TextUtils.isEmpty(tmpInfoBean.depAppName) && !TextUtils.isEmpty(tmpInfoBean.depAppVersion)) {
            builder.append("\n\n- 组件依赖:${tmpInfoBean.depAppName} ${tmpInfoBean.depAppVersion}")
        }
        if (!TextUtils.isEmpty(tmpInfoBean.tmpAccount)) {
            builder.append("\n\n- 提测账号:${tmpInfoBean.tmpAccount}")
        }
        return builder.toString()
    }

    String getGitInfo(Project project) {
        // 获取Git信息
        def gitBranch = getGitCommandResult(project, "git rev-parse --abbrev-ref HEAD")
        def gitCommitHash = getGitCommandResult(project, "git rev-parse HEAD")
        def shortCommitHash = getGitCommandResult(project, "git rev-parse --short HEAD")
        def lastCommitMessage = getGitCommandResult(project, "git log -1 --pretty=%B")
        def commitAuthor = getGitCommandResult(project, "git log -1 --pretty=%an")
        def commitDate = getGitCommandResult(project, "git log -1 --pretty=%cd --date=iso")
        // 打印信息
        println "Git信息:"
        println "----------------------------------------"
        println "分支：         ${gitBranch}"
        println "提交哈希：      ${gitCommitHash}"
        println "简短哈希：      ${shortCommitHash}"
        println "提交信息：      ${lastCommitMessage}"
        println "作者：         ${commitAuthor}"
        println "提交日期：      ${commitDate}"
        println "----------------------------------------"
        return "\n\nGit相关信息：\n\n- message:$lastCommitMessage\n\n- 作者:${commitAuthor}\n\n- 日期:$commitDate\n\n-$gitCommitHash"
    }

    String getFtpFilePath(String localPath) {
        String apkPath = "UN_KNOW"
        if (localPath != null) {
            println("✅ APK 文件地址: $localPath")
            // 上传或其他逻辑
            apkPath = localPath
        } else {
            println("❌ 找不到 APK 文件")
            return ""
        }
        def subContent = "outputs/apk/"
        def indexOf = apkPath.indexOf(subContent)
        def localApkPath = ""
        def ftpParentStr = getFtpParenPath()
        def jenkinsApkName = appName
        if (indexOf >= 0 && (indexOf + subContent.size()) < apkPath.size()) {
            println("✅ substring: ${apkPath.substring(indexOf + subContent.size())}")
            localApkPath = apkPath.substring(indexOf + subContent.size())
        }
        println("ftpParentStr: ${ftpParentStr}")
        println("jenkinsApkName: ${jenkinsApkName}")
        println("localApkPath: ${localApkPath}")
        return ftpParentStr + jenkinsApkName + "/" + localApkPath
    }

    String getFtpParenPath() {
        return "/home/ftpserver/AutoBuildAPK/"
    }

    String getJenkinsApkName() {
        def name = System.getenv('JOB_BASE_NAME')
        println("JOB_BASE_NAME:$name")
        return name
    }

    private ArrayList<String> getAtMobile() {
        List<String> atData = new ArrayList<String>()
        if (ddAtUserMobile != null && ddAtUserMobile.size() > 0) {
            def atList = ddAtUserMobile.split("#")
            if (atList.size() > 0) {
                atData = atList.toList()
            }
        }
        return atData
    }

    private ArrayList<String> getAtUserId() {
        List<String> atData = new ArrayList<String>()
        if ("0" == submitTmpResult) {
            if (ddAtFailUser != null && ddAtFailUser.size() > 0) {
                List<String> user = new ArrayList<String>()
                user.add(ddAtFailUser)
                DingDingUserInfoHelp sunmiUserBean = new DingDingUserInfoHelp();
                atData = sunmiUserBean.getAllDDUser(user)
            }
        } else {
            if (ddAtUser != null && ddAtUser.size() > 0) {
                def atList = ddAtUser.split("#")
                if (atList.size() > 0) {
                    DingDingUserInfoHelp sunmiUserBean = new DingDingUserInfoHelp();
                    atData = sunmiUserBean.getAllDDUser(atList.toList())
                }
            }
        }


        return atData
    }

    def sendMsgToDing(String webHook, String sendMsgStr, String apkPath) {
        println "*************** 准备发送钉钉消息 ***************"
        println "webHook::${webHook}"
        def conn = new URL(webHook).openConnection()
        conn.setRequestMethod('POST')
        conn.setRequestProperty("Connection", "Keep-Alive")
        conn.setRequestProperty("Accept-Charset", "UTF-8")
        conn.setRequestProperty("Content-type", "application/json;charset=utf-8")
        conn.setConnectTimeout(30000)
        conn.setReadTimeout(30000)
        conn.setDoInput(true)
        conn.setDoOutput(true)
        def dos = new DataOutputStream(conn.getOutputStream())
        ArrayList<String> userIds = new ArrayList<>()
        ArrayList<String> userMobiles = new ArrayList<>()
        if ("1" == submitTmpResult) {
            userIds = getAtUserId()
            userMobiles = getAtMobile()
        } else if ("0" == submitTmpResult) {
            userIds = getAtUserId()
        }
        StringBuilder atBuild = new StringBuilder()
        for (String userId : userIds) {
            atBuild.append("@" + userId + " ")
        }
        for (String userMobile : userMobiles) {
            atBuild.append("@" + userMobile + " ")
        }
        def atMsg = ""
        if ("1" == submitTmpResult) {
            atMsg = "[" + atBuild.toString() + "](www.) **${deviceList}**\n\n- TMP提测成功\n\n- ${gitCommitMsg}\n\n- 注意跟踪后续归档流程"
        } else if ("0" == submitTmpResult) {
            atMsg = "[" + atBuild.toString() + "](www.) **TMP 提测失败，请注意查看**"
        }

        def _title = "打包机器人"
        def _content = new StringBuffer()
        _content.append("\n\n${sendMsgStr}")
        _content.append("\n\n" + getJenkinsParam())
        _content.append("\n\n**构建时间:**\n\n" + getCurData())
        _content.append("\n\n**文件地址:**\n\n" + apkPath + "\n\n")
        _content.append("\n\n\n\n![](" + ddPic + ")\n\n")
        _content.append("\n\n" + atMsg)
        def btnData = [
        ]
        if (tmpSubmitUrl != null && tmpSubmitUrl.size() > 0) {
            String ftpsUrlEnc = URLEncoder.encode(tmpSubmitUrl, "UTF-8")
            btnData = [
                    {
                        title "TMP提测入口"
                        actionURL "dingtalk://dingtalkclient/page/link?url=" + ftpsUrlEnc + "&pc_slide=false"
                    }
            ]
        }
        def json = new groovy.json.JsonBuilder()
        json {
            msgtype "actionCard"
            actionCard {
                title _title
                text _content.toString()
                btnOrientation "1"
                btns(btnData)
            }
            at {
                atMobiles(userMobiles)
                atUserIds(userIds)
                isAtAll false
            }
        }

//
//        JSONObject object = new JSONObject()
//        object.put("msgtype", "actionCard")
//        //actionCard
//        JSONObject actionCardObj = new JSONObject()
//        actionCardObj.put("title", _title)
//        actionCardObj.put("text", _content.toString())
//        actionCardObj.put("btnOrientation", "0")
//        //按钮消息
//        actionCardObj.put("btns", getActBtn())
//        object.put("actionCard", actionCardObj)
//
//        //at 消息
//        JSONObject atObj = new JSONObject()
//        atObj.put("atMobiles", userMobiles)
//        atObj.put("atUserIds", userIds)
//        atObj.put("isAtAll", false)
//        object.put("at", atObj)
        println("sendDingNet:${json.toString()}")
        dos.writeBytes(json.toString())
        def input = new BufferedReader(new InputStreamReader(conn.getInputStream()))
        String result = ""
        String line = ""
        while ((line = input.readLine()) != null) {
            result += line
        }
        dos.flush()
        dos.close()
        input.close()
        conn.connect()
        println("*************** $result ***************")
    }

    String getCurData() {
        return new Date().format('yyyy-MM-dd hh:mm:ss');
    }

    String findFinalApkPath(Project project, String buildParam, String version) {
        AppExtension android = (AppExtension) project.getExtensions().findByName("android");
        if (android == null) {
            println("❌ Android AppExtension 未找到");
            return null
        }
        String[] buildParamList = buildParam.split("#")
        println("✅ buildParamList: " + buildParam + ",size:" + buildParamList.size());
        println("✅ getApplicationVariants: " + android.getApplicationVariants().size())
        List<String> allApkPath = new ArrayList<>()
        for (ApplicationVariant variant : android.getApplicationVariants()) {
            for (BaseVariantOutput output : variant.getOutputs()) {
                try {
                    File apk = (File) output.getClass().getMethod("getOutputFile").invoke(output);
                    if (apk != null && apk.exists()) {
                        String path = apk.getAbsolutePath()
                        println("⚠️ apk AbsolutePath: " + path)
                        boolean appPass = true
                        if (path.contains("SunmiOSRes")) {
                            appPass = true
                        } else if (version != null && version.size() > 0) {
                            appPass = path.contains(version)
                        }
                        for (i in 0..<buildParamList.size() - 1) {
                            String indexStr = buildParamList[i]
                            def check = path.toLowerCase().contains(indexStr.toLowerCase())
                            println("⚠️ indexStr: " + indexStr + ",toUpperCase:" + indexStr.toLowerCase() + "check:" + check + ",index:" + i)
                            if (!check) {
                                appPass = false
                            }
                        }
                        if (appPass) {
                            def buildNum = getBuildNum()
                            if (!TextUtils.isBlank(buildNum)) {
                                def newParentDir = path.replace("/apk/", "/apk/${variant.versionName}/${buildNum}/")
                                System.out.println("✅ 获取 APK 路径: " + apk.getAbsolutePath());
                                copyApkFile(apk.getAbsolutePath(), newParentDir)
                                def ftpApk = new File(newParentDir)
                                System.out.println("✅ 获取 APK FTP 路径: " + ftpApk.exists())
                                if (ftpApk.exists()) {
                                    allApkPath.add(newParentDir)
                                }
                            } else {
                                allApkPath.add(apk.getAbsolutePath())
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
        if (allApkPath.size() > 0) {
            return allApkPath.get(0)
        }
        System.out.println("⚠️ 未找到匹配的 APK 输出")
        return null
    }


    private void copyApkFile(String sourceStr, String targetStr) {
        Path source = Paths.get(sourceStr)
        Path target = Paths.get(targetStr)
        println("✅ APK 复制操作 ");
        println("✅ sourceStr:" + sourceStr);
        println("✅ targetStr:" + targetStr);
        try {
            Path targetDir = target.getParent();
            if (!Files.exists(targetDir)) {
                try {
                    Files.createDirectories(targetDir) // 创建所有不存在的父目录
                } catch (Exception e) {
                    e.printStackTrace()
                    throw new GradleException("Failed to create output directory", e);
                }
            }
            println("开始复制APK")
            Files.move(source, target, StandardCopyOption.REPLACE_EXISTING)
        } catch (Exception exception) {
            exception.printStackTrace()
        }
        try {
            File targetFile = new File(targetStr)
            println("复制APK结果:${targetFile.exists()}")
            if (targetFile.exists()) {
                def favParentFile = new File(sourceStr).getParentFile().getParentFile()
                println("删除APK目录:${favParentFile.getAbsolutePath()}")
                favParentFile.deleteDir()
            }
        } catch (Exception exception) {
            exception.printStackTrace()
        }
    }

    String getBuildNum() {
        return System.getenv("BUILD_NUMBER")
    }

    String getJenkinsParam() {
        def allDevValue = System.getenv()
        def listEnv = new ArrayList()
        listEnv.add("GIT_BRANCH")
        listEnv.add("BUILD_URL")
        String allEnv = ""
        for (String envKey : listEnv) {
            if (allDevValue.containsKey(envKey)) {
                String envKeyStr = envKey
                if (envKey.equals("GIT_BRANCH")) {
                    envKeyStr = "Git分支"
                } else if (envKey.equals("BUILD_URL")) {
                    envKeyStr = "Jenkins地址"
                }
                allEnv = allEnv + "- " + envKeyStr + ":" + allDevValue.get(envKey) + "\n\n"
            }
        }
        return allEnv
    }

    private String getGitCommandResult(Project project, String command) {
        try {
            def proc = command.execute(null, project.rootDir)
            proc.waitFor()
            if (proc.exitValue() == 0) {
                return proc.text.trim()
            }
        } catch (Exception e) {
            println("执行Git命令失败: ${e.message}")
        }
        return "unknown"
    }
}
